using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace _3D_Game2
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Camera : Microsoft.Xna.Framework.GameComponent
    {
        public Matrix view { get; protected set; }
        public Matrix projection { get; protected set; }
        
        // Camera vectors
        public Vector3 cameraPosition { get; protected set; }
        Vector3 cameraDirection;
        Vector3 cameraUp;
        Vector3 cameraRotatedTarget = Vector3.Zero;
        float previousCameraX = 0, 
            perviousCameraY=0,currentCameraX =0, currentCameraY=0;
       
        MouseState prevMouseState;
       
        // Max yaw/pitch variables
        float totalYaw = MathHelper.PiOver4 / 2;
        float currentYaw = 0;
        float totalPitch = MathHelper.PiOver4 / 2;
        float currentPitch = 0;


        float speed = 10;

        public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up)
            : base(game)
        {
            // Build camera view matrix
            cameraPosition = pos;
            cameraDirection = target - pos;
            cameraDirection.Normalize();
            cameraUp = up;
            CreateLookAt();
            projection = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.PiOver4,
            (float)Game.Window.ClientBounds.Width /
            (float)Game.Window.ClientBounds.Height,
            0.1f, 10000);
            
            
        }
        public Vector3 getCameraPosition()
        {
            return cameraPosition;
        }

        public Vector3 GetCameraDirection
        {
            get { return cameraDirection; }
        }

        private void CreateLookAt()
        {
            view = Matrix.CreateLookAt(cameraPosition,
            cameraPosition + cameraDirection, cameraUp);

        }

        public override void Initialize()
        {
            // Set mouse position and do initial get state
            //Mouse.SetPosition(Game.Window.ClientBounds.Width / 2,
           // Game.Window.ClientBounds.Height / 2);
           // prevMouseState = Mouse.GetState();

            base.Initialize();
        }
        public Vector3 getCameraUpDirection()
        {
            return cameraUp;
        }
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // Move forward/backward
            if (Keyboard.GetState( ).IsKeyDown(Keys.W))
            cameraPosition += cameraDirection * speed;
            if (Keyboard.GetState( ).IsKeyDown(Keys.S))
            cameraPosition -= cameraDirection * speed;
            // Move side to side
            if (Keyboard.GetState( ).IsKeyDown(Keys.A))
            cameraPosition += Vector3.Cross(cameraUp, cameraDirection) * speed;
            if (Keyboard.GetState( ).IsKeyDown(Keys.D))
            cameraPosition -= Vector3.Cross(cameraUp, cameraDirection) * speed;


            //if (Keyboard.GetState().IsKeyDown(Keys.Right))
            //{
            //    currentCameraX = previousCameraX + 2f;
            //    float yawAngle = (-MathHelper.PiOver4 / 150) * (currentCameraX - previousCameraX);
            //    //if (Math.Abs(currentYaw + yawAngle) < totalYaw)
            //    //{
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(cameraUp, yawAngle));
            //    currentYaw += yawAngle;
            //}
            //if (Keyboard.GetState().IsKeyDown(Keys.Left))
            //{
            //    currentCameraX = previousCameraX - 2f;
            //    float yawAngle = (-MathHelper.PiOver4 / 150) * (currentCameraX);
            //    //if (Math.Abs(currentYaw + yawAngle) < totalYaw)
            //    //{
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(cameraUp, yawAngle));
            //    currentYaw += yawAngle;
            //}

            //// Pitch rotation
            //if (Keyboard.GetState().IsKeyDown(Keys.Down))
            //{
            //    currentCameraY = perviousCameraY + 2f;
            //    float pitchAngle = (MathHelper.PiOver4 / 150) *
            //    (currentCameraY - perviousCameraY);
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(
            //    Vector3.Cross(cameraUp, cameraDirection),
            //    pitchAngle));
            //    currentPitch += pitchAngle;
            //}

            //if (Keyboard.GetState().IsKeyDown(Keys.Up))
            //{
            //    currentCameraY = perviousCameraY - 2f;
            //    float pitchAngle = (MathHelper.PiOver4 / 150) *
            //    (currentCameraY);
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(
            //    Vector3.Cross(cameraUp, cameraDirection),
            //    pitchAngle));
            //    currentPitch += pitchAngle;
            //}



            // Yaw rotation
            //float yawAngle = (-MathHelper.PiOver4 / 150) * (Mouse.GetState().X - prevMouseState.X);
            ////if (Math.Abs(currentYaw + yawAngle) < totalYaw)
            ////{
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(cameraUp, yawAngle));
            //    currentYaw += yawAngle;
            ////}



            //// Pitch rotation
            //float pitchAngle = (MathHelper.PiOver4 / 150) *
            //(Mouse.GetState().Y - prevMouseState.Y);
            ////if (Math.Abs(currentPitch + pitchAngle) < totalPitch)
            ////{
            //    cameraDirection = Vector3.Transform(cameraDirection,
            //    Matrix.CreateFromAxisAngle(
            //    Vector3.Cross(cameraUp, cameraDirection),
            //    pitchAngle));
            //    currentPitch += pitchAngle;
            ////}

            // Roll rotation
                if (Mouse.GetState( ).LeftButton == ButtonState.Pressed)
                {
                cameraUp = Vector3.Transform(cameraUp,
                Matrix.CreateFromAxisAngle(cameraDirection,
                MathHelper.PiOver4 / 45));
                }
                if (Mouse.GetState( ).RightButton == ButtonState.Pressed)
                {
                cameraUp = Vector3.Transform(cameraUp,
                Matrix.CreateFromAxisAngle(cameraDirection,
                -MathHelper.PiOver4 / 45));
                }



            // Reset prevMouseState
           // prevMouseState = Mouse.GetState();

            // Recreate the camera view matrix
            CreateLookAt();

            base.Update(gameTime);
        }
    }
}
